﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GruntyOS.HAL;
using GruntyOS.IO;
using CosmosHD.Graphics;
using Cosmos.Hardware;
using Cosmos.System;
using Cosmos.Core;

namespace CosmosHD.Graphics
{
    public class Color
    {
        public byte r, g, b;
        #region new
        public Color()
        {
            r = 0;
            g = 0;
            b = 0;
        }
        public Color(byte _r, byte _g, byte _b)
        {
            r = _r;
            g = _g;
            b = _b;
        }
        #endregion
        #region colors
        public static Color Black = new Color(0, 0, 0);
        public static Color White = new Color(255, 255, 255);
        public static Color Grey = new Color(127, 127, 127);
        public static Color LightGrey = new Color(191, 191, 191);
        public static Color DarkGrey = new Color(63, 63, 63);
        public static Color Red = new Color(255, 0, 0);
        public static Color Green = new Color(0, 255, 0);
        public static Color Blue = new Color(0, 0, 255);
        public static Color Yellow = new Color(255, 255, 0);
        public static Color Magenta = new Color(255, 0, 255);
        public static Color Cyan = new Color(0, 255, 255);
        #endregion
        #region methods
        public void Invert()
        {
            r = (byte)(255 - r); g = (byte)(255 - g); b = (byte)(255 - b);
        }
        public static Color Invert(Color c)
        {
            return new Color((byte)(255 - c.r), (byte)(255 - c.b), (byte)(255 - c.g));
        }
        #endregion
    }
    public class Vec2
    {
        public int x, y;
        public static Vec2 Zero = new Vec2(0, 0);
        public static Vec2 One = new Vec2(1, 1);
        public Vec2(int _x, int _y)
        {
            x = _x; y = _y;
        }
    }
    public class VecF
    {
        public float x, y;
        public static VecF Zero = new VecF(0f, 0f);
        public static VecF One = new VecF(1f, 1f);
        public VecF(float _x, float _y)
        {
            x = _x; y = _y;
        }
    }
    public class Image
    {
 
        
        public List<List<Color>> pixels = new List<List<Color>>();
        public void set(Vec2 point, Color color)
        {
            pixels[point.x][point.y] = color;
        }
        public Color get(Vec2 point)
        {
            return pixels[point.x][point.y];
        }
        public Image(List<List<Color>> pxls)
        {
            pixels = pxls;
        }
    }
    //Not implemented, will control screen+drivers
    public static class Screen
    {
        public static Vec2 Res = new Vec2(1300,780);
        public static void Refresh()
        {
        }
        public static void Set(Vec2 point, Color c)
        {
        }
        public static void Fillrect(Vec2 Point, Vec2 Size, Color c)
        {
        }
        public static void Rectborder(Vec2 Point, Vec2 Size, Color c)
        {
        }
        public static void Clear(Color c)
        {
        }
        public static void Stamp(Vec2 point, Image im)
        {
        }
    }
}
namespace CosmosHD.Utils
{
    class HexadecimalConverter
    {
        static Dictionary<char, byte> hexa = new Dictionary<char, byte>();
        static bool isInit = false;
        public static void Init()
        {
            if (!isInit)
            {
                isInit = true;
                string chars = "0123456789ABCDEF";
                byte i = 0;
                foreach (char c in chars)
                {
                    hexa.Add(c, i);
                    i++;
                }
            }
        }
        public static byte tobyte(string hex)
        {
            Init();
            int over = 0;
            byte returns = 0;
            foreach(char c in hex)
            {
                returns += (byte)(hexa[c] << over);
                over += 4;
            }
            return returns;
        }
        public static Int16 toI16(string hex)
        {
            Init();
            int over = 0;
            Int16 returns = 0;
            foreach (char c in hex)
            {
                returns += (Int16)(hexa[c] << over);
                over += 4;
            }
            return returns;
        }
        public static Int32 toI32(string hex)
        {
            Init();
            int over = 0;
            Int32 returns = 0;
            foreach (char c in hex)
            {
                returns += (Int32)(hexa[c] << over);
                over += 4;
            }
            return returns;
        }
        public static Int64 toI64(string hex)
        {
            Init();
            int over = 0;
            Int64 returns = 0;
            foreach (char c in hex)
            {
                returns += (hexa[c] << over);
                over += 4;
            }
            return returns;
        }
    }
}
namespace CosmosHD.Drivers
{
}
namespace CosmosHD.Extensions
{
    namespace Graphics
    {
        public static class ColorExtension
        {
            public static uint ToUint(this Color c)
            {
                return (uint)((c.r << 16) | (c.g << 8) | c.b);
            }
        }
        public static class Vec2Extension
        {
            public static void Negate(this Vec2 vec)
            {
                vec.x = -vec.x; vec.y = -vec.y;
            }
        }
        public static class VecFExtension
        {

            public static void Negate(this VecF vec)
            {
                vec.x = -vec.x; vec.y = -vec.y;
            }
        }
        public static class ImageExtension
        {
            public static void Invert(this Image im)
            {
                foreach (List<Color> l in im.pixels)
                {
                    foreach (Color c in l)
                    {
                        c.Invert();
                    }
                }
            }
        }
    }
}
namespace CosmosHD.Encryption
{
    public abstract class Encryption
    {
        public abstract string Version();
        public abstract byte[] encrypt(byte[] input, int seed);
        public abstract byte[] decrypt(byte[] input, int seed);
    }
    class qfse : Encryption
    {
        static byte[] ini16(Int16 i16)
        {
            return new byte[] { (byte)(i16 / 256), (byte)(i16 % 256) };
        }
        static Int16 outi16(byte one, byte two)
        {
            return (Int16)((one << 8) | two);
        }
        //Not static
        public override string Version()
        {
            return "Quicksilver FSEncryption 1.03";
        }
        public override byte[] encrypt(byte[] input, int seed)
        {
            Random r = new Random(seed);
            byte[] buffer = new byte[input.Length];
            List<byte> rtrn = new List<byte>();
            r.NextBytes(buffer);
            int i = 0;
            foreach (byte b in input)
            {
                Int16 tmp = (Int16)(b * buffer[i]);
                byte[] temp = ini16(tmp);
                rtrn.Add(temp[0]);
                rtrn.Add(temp[1]);
                i++;
            }
            return rtrn.ToArray();
        }
        public override byte[] decrypt(byte[] input, int seed)
        {
            Random r = new Random(seed);
            byte[] buffer = new byte[input.Length / 2];
            List<byte> rtrn = new List<byte>();
            r.NextBytes(buffer);
            int i = 0;
            foreach (byte b in buffer)
            {
                Int16 tmp = outi16(input[2 * i], input[(2 * i) + 1]);
                rtrn.Add((byte)(tmp / b));
                i++;
            }
            return rtrn.ToArray();
        }
    }
}
namespace CosmosHD.Filesystem
{
    abstract class filesystem
    {
        public abstract void partition();
        public abstract void write(byte[] content, string path);
        public abstract byte[] read(string path);
        public abstract void delete();
    }
    class Storage : filesystem
    {
    }
    class EncryptionSys
    {
        filesystem encryptfs;
        Encryption.Encryption en;
        public EncryptionSys(filesystem fs, Encryption.Encryption e)
        {
            encryptfs = fs;
            en = e;
        }
        public void write(int seed, byte[] stream, string path)
        {
            byte[] towrite = en.encrypt(stream, seed);
            encryptfs.write(towrite, path);
        }
        public byte[] read(int seed, string path)
        {
            return en.decrypt(encryptfs.read(path), seed);
        }
    }
}